package com.artisan.springuitls.demos;

import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Method;

/**
 * ClassUtils 工具类演示
 * 功能：类操作安全助手
 * 优势：isPresent() 安全检查类是否存在，避免 Class.forName() 的 ClassNotFoundException
 */
@Component
public class ClassUtilsDemo {

    /**
     * 场景：动态加载功能（如检测 Redis 依赖）
     */
    public boolean isRedisAvailable() {
        System.out.println("\n========== ClassUtils Demo ==========");
        
        // ✅ 安全检查：不加载类
        boolean available = ClassUtils.isPresent(
            "redis.clients.jedis.Jedis", 
            getClass().getClassLoader()
        );
        
        System.out.println("✓ Redis (Jedis) 可用: " + available);
        return available;
    }

    /**
     * 演示类存在性检查
     */
    public void demonstrateClassPresence() {
        System.out.println("\n--- 类存在性检查 ---");
        
        ClassLoader classLoader = getClass().getClassLoader();
        
        // 检查常见类
        String[] classNames = {
            "java.lang.String",
            "org.springframework.util.StringUtils",
            "com.mysql.cj.jdbc.Driver",
            "redis.clients.jedis.Jedis",
            "com.fasterxml.jackson.databind.ObjectMapper"
        };
        
        for (String className : classNames) {
            boolean present = ClassUtils.isPresent(className, classLoader);
            System.out.println("✓ " + className + ": " + (present ? "存在" : "不存在"));
        }
        
        System.out.println();
    }

    /**
     * 演示类信息获取
     */
    public void demonstrateClassInfo() {
        System.out.println("\n--- 类信息获取 ---");
        
        Class<?> clazz = String.class;
        
        // 1. 获取短类名
        String shortName = ClassUtils.getShortName(clazz);
        System.out.println("✓ 短类名: " + shortName); // String
        
        // 2. 获取简单类名（不含包名）
        String simpleName = clazz.getSimpleName();
        System.out.println("✓ 简单类名: " + simpleName); // String
        
        // 3. 获取全限定名
        String qualifiedName = ClassUtils.getQualifiedName(clazz);
        System.out.println("✓ 全限定名: " + qualifiedName); // java.lang.String
        
        // 4. 获取包名
        String packageName = ClassUtils.getPackageName(clazz);
        System.out.println("✓ 包名: " + packageName); // java.lang
        
        // 5. 数组类型处理
        Class<?> arrayClass = String[].class;
        System.out.println("✓ 数组短名: " + ClassUtils.getShortName(arrayClass)); // String[]
        System.out.println("✓ 数组全名: " + ClassUtils.getQualifiedName(arrayClass)); // java.lang.String[]
        
        System.out.println();
    }

    /**
     * 演示类加载和解析
     */
    public void demonstrateClassLoading() {
        System.out.println("\n--- 类加载和解析 ---");
        
        try {
            ClassLoader classLoader = getClass().getClassLoader();
            
            // 1. 解析类名（支持原始类型、数组等）
            Class<?> intClass = ClassUtils.forName("int", classLoader);
            System.out.println("✓ 原始类型: " + intClass); // int
            
            Class<?> stringClass = ClassUtils.forName("java.lang.String", classLoader);
            System.out.println("✓ 普通类: " + stringClass); // class java.lang.String
            
            Class<?> arrayClass = ClassUtils.forName("java.lang.String[]", classLoader);
            System.out.println("✓ 数组类型: " + arrayClass); // class [Ljava.lang.String;
            
            // 2. 解析类名（返回 Class 描述符）
            String descriptor = ClassUtils.convertClassNameToResourcePath(
                "com.artisan.springuitls.demos.ClassUtilsDemo");
            System.out.println("✓ 类路径: " + descriptor); // com/artisan/springuitls/demos/ClassUtilsDemo
            
        } catch (ClassNotFoundException e) {
            System.err.println("✗ 类加载失败: " + e.getMessage());
        }
        
        System.out.println();
    }

    /**
     * 演示接口和类型检查
     */
    public void demonstrateTypeChecking() {
        System.out.println("\n--- 接口和类型检查 ---");
        
        // 1. 检查是否为内部类
        System.out.println("✓ String 是内部类: " + ClassUtils.isInnerClass(String.class)); // false
        
        // 2. 检查是否为 CGLIB 代理类
        System.out.println("✓ String 是 CGLIB 类: false");
        
        // 3. 获取用户类（去除代理）
        Class<?> userClass = ClassUtils.getUserClass(String.class);
        System.out.println("✓ 用户类: " + userClass); // class java.lang.String
        
        // 4. 检查是否可见
        System.out.println("✓ String 可见: " + ClassUtils.isVisible(String.class, 
            getClass().getClassLoader())); // true
        
        // 5. 检查是否为原始类型
        System.out.println("✓ int 是原始类型: " + ClassUtils.isPrimitiveOrWrapper(int.class)); // true
        System.out.println("✓ Integer 是原始类型包装: " + ClassUtils.isPrimitiveOrWrapper(Integer.class)); // true
        
        System.out.println();
    }

    /**
     * 演示方法相关操作
     */
    public void demonstrateMethodOperations() {
        System.out.println("\n--- 方法相关操作 ---");
        
        try {
            Method method = String.class.getMethod("substring", int.class, int.class);
            
            // 1. 获取方法的简短描述
            String shortName = ClassUtils.getQualifiedMethodName(method);
            System.out.println("✓ 方法全名: " + shortName);
            
            // 2. 检查方法是否可覆盖
            System.out.println("✓ 方法可覆盖: " + !java.lang.reflect.Modifier.isFinal(method.getModifiers()));
            
        } catch (NoSuchMethodException e) {
            System.err.println("✗ 方法未找到");
        }
        
        System.out.println();
    }

    /**
     * 演示类型转换
     */
    public void demonstrateTypeConversion() {
        System.out.println("\n--- 类型转换 ---");
        
        // 1. 原始类型转包装类型
        Class<?> intWrapper = ClassUtils.resolvePrimitiveIfNecessary(int.class);
        System.out.println("✓ int 解析为: " + intWrapper); // class java.lang.Integer
        
        Class<?> stringType = ClassUtils.resolvePrimitiveIfNecessary(String.class);
        System.out.println("✓ String 解析为: " + stringType); // class java.lang.String
        
        // 2. 获取原始类型的默认值
        System.out.println("✓ boolean 默认值: " + false);
        System.out.println("✓ int 默认值: " + 0);
        
        System.out.println();
    }

    /**
     * 实际应用场景：条件化配置
     */
    public void demonstrateConditionalConfiguration() {
        System.out.println("\n--- 条件化配置场景 ---");
        
        ClassLoader classLoader = getClass().getClassLoader();
        
        // 检测数据库驱动
        boolean mysqlPresent = ClassUtils.isPresent("com.mysql.cj.jdbc.Driver", classLoader);
        boolean postgresPresent = ClassUtils.isPresent("org.postgresql.Driver", classLoader);
        boolean h2Present = ClassUtils.isPresent("org.h2.Driver", classLoader);
        
        System.out.println("✓ 可用的数据库驱动:");
        if (mysqlPresent) System.out.println("  - MySQL");
        if (postgresPresent) System.out.println("  - PostgreSQL");
        if (h2Present) System.out.println("  - H2");
        
        // 检测 JSON 库
        boolean jacksonPresent = ClassUtils.isPresent(
            "com.fasterxml.jackson.databind.ObjectMapper", classLoader);
        boolean gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
        
        System.out.println("✓ 可用的 JSON 库:");
        if (jacksonPresent) System.out.println("  - Jackson");
        if (gsonPresent) System.out.println("  - Gson");
        
        // 检测缓存框架
        boolean redisPresent = ClassUtils.isPresent("redis.clients.jedis.Jedis", classLoader);
        boolean caffeinePresent = ClassUtils.isPresent("com.github.benmanes.caffeine.cache.Caffeine", classLoader);
        
        System.out.println("✓ 可用的缓存框架:");
        if (redisPresent) System.out.println("  - Redis");
        if (caffeinePresent) System.out.println("  - Caffeine");
        
        System.out.println();
    }

    /**
     * 实际应用场景：Spring Boot 自动配置
     */
    public void demonstrateAutoConfiguration() {
        System.out.println("\n--- 自动配置场景 ---");
        
        System.out.println("✓ 在 Spring Boot 自动配置中使用:");
        System.out.println("");
        System.out.println("@Configuration");
        System.out.println("@ConditionalOnClass(name = \"redis.clients.jedis.Jedis\")");
        System.out.println("public class RedisAutoConfiguration {");
        System.out.println("    // Redis 配置");
        System.out.println("}");
        System.out.println("");
        System.out.println("或使用 ClassUtils 手动检查:");
        System.out.println("");
        System.out.println("if (ClassUtils.isPresent(\"redis.clients.jedis.Jedis\", classLoader)) {");
        System.out.println("    // 启用 Redis 功能");
        System.out.println("}");
        
        System.out.println("==========================================\n");
    }

    /**
     * 最佳实践
     */
    public void printBestPractices() {
        System.out.println("\n========== 最佳实践 ==========");
        System.out.println("✓ 1. 使用 isPresent() 检查可选依赖");
        System.out.println("✓ 2. 条件化 Bean 定义时使用此工具");
        System.out.println("✓ 3. 适配多环境依赖（如多数据库驱动）");
        System.out.println("✓ 4. 不要过度使用类检查，优先依赖注入");
        System.out.println("✓ 5. 结合 @ConditionalOnClass 实现自动配置");
        System.out.println("✓ 6. getUserClass() 去除 CGLIB 代理影响");
        System.out.println("==========================================\n");
    }
}

